package ua.dlab.ui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class Step1 implements Step {
	private JComponent pnlMain = null;
	private JSpinner txfSize = null;
	private JSpinner txfEps = null;
	private Step nextStep = null;
	private double matrix[][] = null;
	
	public Step1() {
		
	}
	
	private void init() {
		pnlMain = new JPanel(new GridBagLayout());
		txfSize = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
		txfEps = new JSpinner(new SpinnerNumberModel(0, 0, 1, 0.001));
		
		txfSize.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent arg0) {
				nextStep = null;
			}
		});
		
		txfEps.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent arg0) {
				nextStep = null;
			}
		});
		
		pnlMain.add(new JLabel("Enter matrix size:"), 
				new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,
						GridBagConstraints.NONE, new Insets(6, 6, 6, 6), 0, 0));
		pnlMain.add(txfSize, 
				new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
						GridBagConstraints.HORIZONTAL, new Insets(6, 0, 6, 6), 0, 0));
		pnlMain.add(new JLabel("Введіть обмеження:"), 
				new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,
						GridBagConstraints.NONE, new Insets(6, 6, 6, 6), 0, 0));
		pnlMain.add(txfEps, 
				new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
						GridBagConstraints.HORIZONTAL, new Insets(6, 0, 6, 6), 0, 0));
		pnlMain.add(new JPanel(), 
				new GridBagConstraints(0, 2, 2, 1, 1, 1, GridBagConstraints.NORTHWEST,
						GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
	}

	@Override
	public boolean hashNext() {
		return true;
	}

	@Override
	public Step nextStep() {
		if (nextStep == null) {
			nextStep = new Step2((int)txfSize.getValue(), (double)txfEps.getValue(), matrix) {
				@Override
				public Step previousStep() {
					return Step1.this;
				}
			};
		}
		
		return nextStep;
	}

	@Override
	public JComponent getMainArea() {
		if (pnlMain == null) {
			init();
		}
		
		return pnlMain;
	}

	@Override
	public boolean hashPrevious() {
		return false;
	}

	@Override
	public Step previousStep() {
		return null;
	}

	@Override
	public Action getAction() {
		return new AbstractAction("Load") {
			private static final long serialVersionUID = 1L;

			@Override
			public void actionPerformed(ActionEvent e) {
				load();
			}
		};
	}
	
	private void load() {
		JFileChooser jfcOpen = new JFileChooser();
		jfcOpen.setFileFilter(new FileNameExtensionFilter("Xml files (*.xml)", "xml"));
		
		if (jfcOpen.showOpenDialog(pnlMain) == JFileChooser.APPROVE_OPTION) {
			try {
				open(jfcOpen.getSelectedFile());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void open(File selectedFile) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
		Document doc = documentBuilder.parse(selectedFile);

		doc.getDocumentElement().normalize();  
		
		Node rootNode = doc.getFirstChild();
		while (rootNode != null && rootNode.getNodeType() == Node.ELEMENT_NODE) {
			Element rootElement = (Element)rootNode;
			
			if (rootElement.getTagName().equals("data")) {
				int size = Integer.parseInt(rootElement.getAttribute("size"));
				txfSize.setValue(size);
				txfEps.setValue(Double.parseDouble(rootElement.getAttribute("eps")));
				
				matrix = new double[size][size + 1];
				
				int i = 0;
				Node rowNode = rootElement.getFirstChild();
				while (rowNode != null && rowNode.getNodeType() == Node.ELEMENT_NODE) {
					Element rowElement = (Element)rowNode;
					
					int j = 0;
					Node cellNode = rowElement.getFirstChild();
					while (cellNode != null && cellNode.getNodeType() == Node.ELEMENT_NODE) {
						Element cellElement = (Element)cellNode;
						
						matrix[i][j++] = Double.parseDouble(cellElement.getTextContent());
						
						cellNode = cellNode.getNextSibling();
					}
					
					i++;
					
					rowNode = rowNode.getNextSibling();
				}
			}
			
			rootNode = rootNode.getNextSibling();
		}
	}
}
